package cn.common;


import cn.common.annotation.KafkaMetaMessage;
import cn.common.dto.RetryRequestParamDTO;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.util.config.HttpResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.retry.RecoveryCallback;
import org.springframework.retry.RetryCallback;
import org.springframework.retry.RetryContext;
import org.springframework.retry.support.RetryTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Map;
import java.util.Objects;


/**
 * Copyright
 *
 * @Author WuHuang
 * @Date 2022/12/21
 */
@Service
public class RetryService {
    private static final Logger log = LoggerFactory.getLogger(RetryService.class);
    @Resource
    private KafkaTemplate<Integer, KafkaMetaMessage> kafkaRetryTemplate;

    public RetryService() {
    }

    public HttpResult retry(RetryTemplate retryTemplate, final RetryRequestParamDTO requestDto, final RetryWorkerService retryWork) throws Throwable {
        HttpResult result = (HttpResult)retryTemplate.execute(new RetryCallback<HttpResult, Throwable>() {
            public HttpResult doWithRetry(RetryContext retryContext) throws Throwable {
                Map<String, Object> metaMap = requestDto.getMetaMap();
                Integer lastCount = (Integer)metaMap.get("basicRetry_curRetryCount");
                metaMap.put("basicRetry_curRetryCount", lastCount + 1);
                String retryNo = (String)metaMap.get("basicRetry_retryNO");
                RetryService.log.info("spring-retry,retryNo:{}当前重试第{}次,request:{}", new Object[]{retryNo, lastCount, JSONObject.toJSONString(requestDto)});

                try {
                    HttpResult httpResult = retryWork.doWork(requestDto);
                    if (Objects.nonNull(httpResult) && httpResult.isSuccess()) {
                        RetryService.log.info("springretry重试成功,retryNo:{},当前重试第{}次", retryNo, lastCount);
                        KafkaMetaMessage kafkaMetaMessage = new KafkaMetaMessage();
                        kafkaMetaMessage.setData(retryNo);
//                        RetryService.this.kafkaRetryTemplate.send("basic_retry_idempotent_topic", kafkaMetaMessage);
                        return httpResult;
                    } else {
                        retryContext.setAttribute("retryParam", requestDto);
                        throw new Exception("springretry重试失败异常");
                    }
                } catch (Exception var7) {
                    retryContext.setAttribute("retryParam", requestDto);
                    throw new Exception("springretry重试失败异常");
                }
            }
        }, new RecoveryCallback<HttpResult>() {
            public HttpResult recover(RetryContext retryContext) throws Exception {
                RetryRequestParamDTO RetryRequestParamDTO = (RetryRequestParamDTO)retryContext.getAttribute("retryParam");
                RetryService.log.error("同步重试最终失败失败{}", JSON.toJSONString(RetryRequestParamDTO));
                return HttpResult.fail("重试失败");
            }
        });
        return result;
    }
}

